/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.hadoop.hdfs.server.hightidenode.metrics;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.metrics.MetricsContext;
import org.apache.hadoop.metrics.MetricsRecord;
import org.apache.hadoop.metrics.MetricsUtil;
import org.apache.hadoop.metrics.Updater;
import org.apache.hadoop.metrics.util.MetricsBase;
import org.apache.hadoop.metrics.util.MetricsRegistry;
import org.apache.hadoop.metrics.util.MetricsTimeVaryingLong;
import org.apache.hadoop.metrics.util.MetricsLongValue;
import org.apache.hadoop.metrics.jvm.JvmMetrics;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hdfs.server.hightidenode.HighTideNode;

/**
 * 
 * This class is for maintaining  the various HighTideNode activity statistics
 * and publishing them through the metrics interfaces.
 * This also registers the JMX MBean for RPC.
 * <p>
 * This class has a number of metrics variables that are publicly accessible;
 * these variables (objects) have methods to update their values;
 *  for example:
 *  <p> {@link #syncs}.inc()
 *
 */

public class HighTideNodeMetrics implements Updater {
  public static final Log LOG = LogFactory.getLog(
      "org.apache.hadoop.hdfs.server.hightidenode.metrics.HighTideNodeMetrics");

  private final MetricsRecord metricsRecord;
  public MetricsRegistry registry = new MetricsRegistry();

  private HighTideNodeActivityMBean hightidenodeActivityMBean;

  public MetricsTimeVaryingLong fixAttempt =
                          new MetricsTimeVaryingLong("FixAttempted", registry);
  public MetricsTimeVaryingLong fixFailedModTimeMismatch =
                          new MetricsTimeVaryingLong("FixFailedModTimeMismatch", registry);
  public MetricsTimeVaryingLong fixFailedBlockSizeMismatch =
                          new MetricsTimeVaryingLong("FixFailedBlockSizeMismatch", registry);
  public MetricsTimeVaryingLong fixFailedFileLengthMismatch =
                          new MetricsTimeVaryingLong("FixFailedFileLengthMismatch", registry);
  public MetricsTimeVaryingLong fixFailedNoGoodBlock =
                          new MetricsTimeVaryingLong("FixFailedNoGoodBlock", registry);
  public MetricsTimeVaryingLong fixFailedDatanodeError =
                          new MetricsTimeVaryingLong("FixFailedDatanodeError", registry);
  public MetricsTimeVaryingLong fixClearedOut =
                          new MetricsTimeVaryingLong("FixClearedOut", registry);
  public MetricsTimeVaryingLong fixSuccessfullyStarted =
                          new MetricsTimeVaryingLong("FixSuccessfullyStarted", registry);

  public MetricsTimeVaryingLong filesMatched =
                          new MetricsTimeVaryingLong("NumberOfFilesMatched", registry);
  public MetricsTimeVaryingLong filesChanged =
                          new MetricsTimeVaryingLong("NumberOfFilesChanged", registry);
  public MetricsLongValue savedSize =
                          new MetricsLongValue("SavedSize", registry);

  public HighTideNodeMetrics(Configuration conf, HighTideNode hightideNode) {
    String sessionId = conf.get("session.id");
    // Initiate Java VM metrics
    JvmMetrics.init("HighTideNode", sessionId);


    // Now the Mbean for the name node - this also registers the MBean
    hightidenodeActivityMBean = new HighTideNodeActivityMBean(registry);

    // Create a record for HighTideNode metrics
    MetricsContext metricsContext = MetricsUtil.getContext("dfs");
    metricsRecord = MetricsUtil.createRecord(metricsContext, "hightidenode");
    metricsRecord.setTag("sessionId", sessionId);
    metricsContext.registerUpdater(this);
    LOG.info("Initializing HighTideNodeMetrics using context object:" +
              metricsContext.getClass().getName());
  }

  public void shutdown() {
    if (hightidenodeActivityMBean != null)
      hightidenodeActivityMBean.shutdown();
  }

  /**
   * Since this object is a registered updater, this method will be called
   * periodically, e.g. every 5 seconds.
   */
  public void doUpdates(MetricsContext unused) {
    synchronized (this) {
      for (MetricsBase m : registry.getMetricsList()) {
        m.pushMetric(metricsRecord);
      }
    }
    metricsRecord.update();
  }

  /**
   * Clear out all metrics that are min or max
   */
  public void resetAllMinMax() {
  }
}
